package com.github.blanexie.nexusj.torrent.domain.entity

import com.github.blanexie.nexusj.support.database
import com.github.blanexie.nexusj.application.dto.PeerDTO
import com.github.blanexie.nexusj.torrent.infra.repository.PeerDO
import org.ktorm.dsl.*
import java.time.LocalDateTime

data class PeerDO(
    val peerId: String,
    val infoHash: String,
    val authKey: String,
    var trackerid: String?,
    var port: Int,
    var uploaded: Long,
    var downloaded: Long,
    var left: Long,
    var compact: Int,
    var event: String,
    var ip: String?,
    var ipv6: String?,
    var numwant: Int,
    val createTime: LocalDateTime = LocalDateTime.now(),
    var updateTime: LocalDateTime = LocalDateTime.now(),
    var status: Int = 0  //默认0 , 如果1 就是表示这个peerId被禁用了
) {

    /**
     * 封禁
     */
    fun banned() {
        this.status = 1
    }

    /**
     * 刷新数据
     */
    fun refresh(peerDTO: PeerDTO) {
        assert(peerDTO.peerId == this.peerId)
        assert(peerDTO.infoHash == this.infoHash)
        assert(peerDTO.authKey == this.authKey)
        assert(peerDTO.status == 1)

        this.trackerid = peerDTO.trackerid
        this.port = peerDTO.port
        this.uploaded = peerDTO.uploaded
        this.downloaded = peerDTO.downloaded
        this.left = peerDTO.left
        this.compact = peerDTO.compact
        this.event = peerDTO.event
        this.ip = peerDTO.ip
        this.ipv6 = peerDTO.ipv6
        this.numwant = peerDTO.numwant
        this.updateTime = LocalDateTime.now()
    }

    fun save() {
        val id = database().from(PeerDO).select(PeerDO.id).where {
            (PeerDO.peerId eq peerId) and (PeerDO.infoHash eq infoHash) and (PeerDO.authKey eq authKey)
        }.map { row -> row.getInt("id") }.last()


        if (id != null) {
            database().update(PeerDO) {
                set(it.infoHash, infoHash)
                set(it.authKey, authKey)
                set(it.peerId, peerId)
                set(it.compact, compact)
                set(it.createTime, createTime)
                set(it.downloaded, downloaded)
                set(it.event, event)
                set(it.ip, ip)
                set(it.ipv6, ipv6)
                set(it.left, left)
                set(it.numwant, numwant)
                set(it.peerId, peerId)
                set(it.port, port)
                set(it.status, status)
                set(it.trackerid, trackerid)
                set(it.updateTime, LocalDateTime.now())
                set(it.uploaded, uploaded)
                where {
                    it.id eq id
                }
            }
        } else {
            database().insertAndGenerateKey(PeerDO) {
                set(it.infoHash, infoHash)
                set(it.authKey, authKey)
                set(it.peerId, peerId)
                set(it.compact, compact)
                set(it.createTime, createTime)
                set(it.downloaded, downloaded)
                set(it.event, event)
                set(it.ip, ip)
                set(it.ipv6, ipv6)
                set(it.left, left)
                set(it.numwant, numwant)
                set(it.peerId, peerId)
                set(it.port, port)
                set(it.status, status)
                set(it.trackerid, trackerid)
                set(it.updateTime, LocalDateTime.now())
                set(it.uploaded, uploaded)
            }
        }
    }

}

/**
 * 实体工厂
 */
object PeerFactory {

    fun findFromDb(peerId: String, infoHash: String, authKey: String): PeerDO {
        return database().from(PeerDO).select().where {
            (PeerDO.peerId eq peerId) and (PeerDO.infoHash eq infoHash) and (PeerDO.authKey eq authKey)
        }.map { row ->
            val infoHash = row[PeerDO.infoHash]
            val authKey = row[PeerDO.authKey]
            val compact = row[PeerDO.compact]
            val createTime = row[PeerDO.createTime]
            val downloaded = row[PeerDO.downloaded]
            val event = row[PeerDO.event]
            val ip = row[PeerDO.ip]
            val ipv6 = row[PeerDO.ipv6]
            val left = row[PeerDO.left]
            val numwant = row[PeerDO.numwant]
            val peerId = row[PeerDO.peerId]
            val port = row[PeerDO.port]
            val status = row[PeerDO.status]
            val trackerid = row[PeerDO.trackerid]
            val updateTime = row[PeerDO.updateTime]
            val uploaded = row[PeerDO.uploaded]

            PeerDO(
                peerId!!, infoHash!!, authKey!!, trackerid, port!!, uploaded!!, downloaded!!, left!!,
                compact!!, event!!, ip, ipv6, numwant!!, createTime!!, updateTime!!, status!!
            )
        }.last()
    }

    fun create(peerDTO: PeerDTO): PeerDO {
        val findFromDb = findFromDb(peerDTO.peerId, peerDTO.infoHash, peerDTO.authKey)
        assert(findFromDb == null)
        var trackerid: String? = peerDTO.peerId
        var port: Int = peerDTO.port
        var uploaded: Long = peerDTO.uploaded
        var downloaded: Long = peerDTO.downloaded
        var left: Long = peerDTO.left
        var compact: Int = peerDTO.compact
        var event: String = peerDTO.event
        var ip: String? = peerDTO.ip
        var ipv6: String? = peerDTO.ipv6
        var numwant: Int = peerDTO.numwant
        return PeerDO(
            peerDTO.peerId, peerDTO.infoHash, peerDTO.authKey, trackerid, port,
            uploaded, downloaded, left, compact, event, ip, ipv6, numwant
        )
    }

}